#if !defined(_CASTAGE_LAYER_H_)
#define _CASTAGE_LAYER_H_

#include "AObject.h"

#include "AXML.h"
//class CAXML;
//class CAXMLNode;
//class CAXMLNodes;
class CAStage;

//#include "AStage.h"
#include "ASprite.h"
#include "ASpriteContainer.h"
#include "AAnimateObject.h"
#include "AMachine.h"

#define DELCARE_STATE_HANDLER(name) \
	void _onStateBegin##name(CAState* pstate); \
	void _onStateEnd##name(CAState* pstate);

//typedef CCNode CAStageLayerBase;
class CAStageLayer : public CCNode, public CASpriteContainer, public CAAnimateObject, public CAMachine
{
private:
	//CAString	_state;
	//ccTime  _timeStateBegin;
protected:
	CAString _name;

	CAStage* _pstage;
	CAStageLayer* _playerParent;
	CAStringMap<CAStageLayer>* _sublayers;
	CAStageLayer* _getSubLayer(const CAString& name)
	{
		return (CAStageLayer*)_sublayers->objectForKey(name);
	}
	CASettings _settings;

	bool _setSpritesState(const char* state, CASprite** pSprites);
	bool _trySetSpritesState(const char* state, const char** pszSprites);
	bool _checkSpritePoseFinished(const char* pszPose, CASprite** psprs);

	//instructure
#	define Init_Sprite_Getter_Var(name) _pSprite_##name = null
#	define Define_Sprite_Getter(type, name) \
	type* _pSprite_##name; \
	inline type* _##name() { \
		return _pSprite_##name; \
	} 
#	define Init_Sprite_Getter(type, name) { \
		_Assert(null == _pSprite_##name); \
		_pSprite_##name = (type*)_getNamedSprite(#name); \
	} 

	class _timeline : public CAObject
	{
	protected:
		class _emmitor
		{
		public:
			class _candidate
			{
			public:
				typedef enum enumCandidateType
				{
					CANDIDATE_SPRITE,
					CANDIDATE_PATTERN,
				}
				ECandidateType;
				ECandidateType type; //sprite or sprites pattern
				CAString object;
				CAString pose;
				CAString gname;
				float percent;
				map<CAString, CAString> settings;
				void initialize(CAXMLNode* pnode);
			};

			CAFixArray<_candidate> candidates;
			//start point
			float xStartO, yStartO, zStartO;
			//random dimision
			float xRange, yRange, zRange;

			CCRect live;
			bool follow;
			float speed; //override speed

			float xStart, yStart, zStart;
			CAFixArray<CASprite*> instances;
			//bool bUsed;

			CASprite* _createSprite(const char* src, const CCPoint& init, const CAString& initpose,
				CAStageLayer* pLayer, _timeline* ptl, const CAString& gname, const map<CAString, CAString>* psettings = null);

			bool processInstancedSprites(_timeline* ptl);
			bool update(CAStageLayer* pLayer, _timeline* ptl, float xpos, float range, _emmitor* peLastForChaining, CCSize* psizeChain);
			void show(bool visble);
			void clean();

			void initialize(CAXMLNode* pnode);
		};
		class _sprite
		{
		public:
			//start point
			float xStart, yStart, zStart;
			CAString spr;
			CAString pose;
			void initialize(CAXMLNode* pnode);
		};
		CAStageLayer* _pLayer;
	public:
		//define
		_timeline(CAStageLayer* pLayer)
		{
			_pLayer = pLayer;
			sprites = CCArray::array();
			sprites->retain();
		}
		virtual ~_timeline()
		{
			remove();
			sprites->release();
			sprites = null;
			_pLayer = null;
		}
		CAString name;
		EAnimationMode mode;
		float range;
		//bool globaltimer;
		bool chain;
		bool visible;
		CCSize chaindist;
		CAFixArray<_emmitor> emmitors;

		//runtime
#define TLS_Disabled	0
#define TLS_Running		1
#define TLS_Removing	2
		int state;
		CCArray* sprites;
		void addSprite(CASprite* pspr);
		void removeSprite(CASprite* pspr);

		size_t curpos;

		void initialize(CAXMLNode* pnode);
		void active();
		void remove();
		void show(bool v = true);

		void update();
	};

	bool _bPaused;
	ccTime	_timePaused;
	float _timeOffset;

	CAStringMap<_timeline> _timelines;

	void _initTimelines(CAXMLNodes* pnodes);

	CCArray* _paryControls; 
	void _tryRemoveControllableSprite(CASprite* pspr);
public:
	CAStageLayer(CAStage* pstage, CAStageLayer* playerParent);
	virtual ~CAStageLayer(void);

	//builder
	virtual int build(CAXMLNode* pnode, CAXMLNode* pnodeRef);

	//getters and settings
	const CAString& name() const { return _name; }
	virtual CAString debuglog() { return ""; }
	CAStage* stage() { return _pstage; };
	
	virtual void pause(bool bsub = false);
	virtual void resume(bool bsub = false);

	virtual float getTimeTotal() const;
	virtual float getTimeNow() const;
	virtual float getTimeDelta() const;

	void activeTimeline(const CAString& name);
	void removeTimeline(const CAString& name);
	void activeAllTimelines();
	void removeAllTimelines();
	void showTimeline(const CAString& name, bool v);
	//void enableTimeline(const CAString& name, bool e, bool bCleanOrCreate = false);

	//events
	virtual void onEnter();
	virtual void onUpdate();
	virtual void onExit();
	virtual void onEvent(CAEvent* pevt);

	virtual bool checkCondition(CAState* from, const CATransition& trans);

	void addControl(CASprite* pspr);
	void removeControl(CASprite* pspr);
	virtual void removeSprite(CASprite* pspr);
};

#endif //_CASTAGE_LAYER_H_